/*  ----------------------------------------------------------------------------
 *  Arello Mobile
 *  Fast 3d Engine
 *  ----------------------------------------------------------------------------
 * Except where otherwise noted, this work is licensed under
 * http://creativecommons.org/licenses/by/3.0
 */
#pragma once

#include <boost/scoped_ptr.hpp>

#include "Texture.h"
#include <SharedRep.h>
#include <AutoContainer.h>
#include <vector>
#include <Atom.h>
#include <HardwareDependentObject.h>
#include <pictureformat/Loader.h>
#include <lib3d/hard/Hardware.h>
#include <lib3d/hard/Manager.h>
#include <filesystem/String.hpp>
#include <CompilerFeatures.h>
#include <sstream>

namespace liba {
namespace lib3d {
namespace material {

class TextureSimpleName : public xml::ObjectANSI
{
public:
	virtual bool on_attribute( xml::Provider * prov, const std::string & name, const std::string & value ) LIBA_OVERRIDE;

	TextureSimpleName()
	: wrap( true )
	, hardware(NULL)
	, texture(NULL)
	{}
	
	TextureSimpleName(hard::Hardware * hardware, hard::Texture * texture)
	: wrap( true )
	, hardware(hardware)
	, texture(texture)
	{
		std::stringstream sstr;
		sstr << (unsigned int)texture << (unsigned int)hardware;
		image = sstr.str().c_str();
	}

	TextureSimpleName(filesystem::String src, bool wrap)
	: image(src)
	, wrap(wrap)
	, hardware(NULL)
	, texture(NULL)
	{ }

	bool operator<( const TextureSimpleName & na )const;

	filesystem::String image;
	bool wrap;
	hard::Hardware * hardware;
	hard::Texture * texture;
};

class TextureSimpleRep : public HardwareDependentObject<hard::Manager, hard::Texture>, public SharedPrecachedRepBase
{
public:
	TextureSimpleRep(const TextureSimpleName & name)
		: pl( 0 )
		, alpha_channel( 0 )
		, width(0)
		, height(0)
	{
		if(name.hardware != NULL)
		{
			hard::Manager::add_dependent(this);
			
			for(HardVector::iterator it = hard_vector.begin(); it != hard_vector.end(); ++it)
			{
				if(it->first == name.hardware)
					it->second = name.texture;
			}
			
			this->width         = name.texture->get_width();
			this->height        = name.texture->get_height();
			this->alpha_channel = true;
			
			stop_loading();
		}
		else
		{
			if( !pl )
				pl.reset(new pictureformat::Loader(name.image));
			
			hard::Manager::add_dependent( this );
		}
	}
	~TextureSimpleRep()
	{
		hard::Manager::remove_dependent( this );
	}
	void load(const TextureSimpleName & name);
	void render_to_list( hard::Hardware * hardware, hard::RenderTexture * render_texture );
	
	//only RGBA supported
	void set_raw_data(void * data, int width, int height);

	int get_width(bool forceLoad = false);
	int get_height(bool forceLoad = false);
protected:
	virtual void on_add_hardware(hard::Manager::hardware_type * ha) LIBA_OVERRIDE;
private:
	boost::scoped_ptr<pictureformat::Loader> pl;
	bool alpha_channel;
	int width;
	int height;
};

class TextureSimple : public Texture, public SharedPrecached<TextureSimpleName, TextureSimpleRep>
{
public:
	typedef name_type Name;

	TextureSimple(const Atom & animate_node_name, const TextureSimpleName & name);
	TextureSimple(hard::Hardware * hardware, hard::Texture * texture);
	TextureSimple(const TextureSimple& rhs);

	virtual TextureSimple * clone()const;

	virtual void render_to_list( hard::Hardware * hardware, hard::RenderTexture * render_texture )
	{
		Texture::render_to_list( hardware, render_texture );
		return get_rep()->render_to_list( hardware, render_texture );
	}
	
	//only RGBA supported
	void set_raw_data(void * data, int width, int height);
private:
	void imageChanged(const filesystem::String& newValue);
	properties::DependencyProperty<filesystem::String> image;
};


} // namespace material
} // namespace lib3d
} // namespace liba
using namespace liba;

